// PresencePage.cs
// Facebook/Framework/Service
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using Facebook.Service.Core;

namespace Facebook.Service {

    /// <summary>
    /// Represents a Facebook page which provides presence to an entity such as
    /// a business, artist, band, product etc.
    /// </summary>
    public sealed class PresencePage : FacebookEntity {

        /// <summary>
        /// The collection of basic fields identifying a page.
        /// </summary>
        public const string BasicFields =
            "page_id,name,type";

        /// <summary>
        /// The collection of fields representing the company information on the page.
        /// </summary>
        public const string CompanyFields =
            BasicFields +
            ",founded,mission,company_overview,products,ticker_symbol";

        /// <summary>
        /// The collection of fields representing the local business information on the page.
        /// </summary>
        public const string BusinessFields =
            BasicFields +
            ",location,parking,public_transit,hours";

        /// <summary>
        /// The collection of fields representing the restaurant information on the page.
        /// </summary>
        public const string RestaurantFields =
            BusinessFields +
            ",attire,payment_options,culinary_team,general_manager,price_range,restaurant_services,restaurant_specialities";

        /// <summary>
        /// The collection of fields representing the TV show or film information on the page.
        /// </summary>
        public const string ShowFields =
            BasicFields +
            ",genre,release_date,starring,screenplay_by,directed_by,produced_by,studio,awards,plot_outline,network,season,schedule,written_by";

        /// <summary>
        /// The collection of fields representing the band information on the page.
        /// </summary>
        public const string BandFields =
            BasicFields +
            ",hometown,current_location,band_members,record_label,booking_agent,artists_we_like,influences,band_interests";

        /// <summary>
        /// The collection of fields representing the personal information on the page.
        /// </summary>
        public const string PersonalFields =
            BasicFields +
            ",location,birthday,bio,affiliation,personal_info,personal_interests";

        /// <summary>
        /// The collection of fields representing all information on the page.
        /// </summary>
        public const string AllFields =
            "page_id,name,pic_small,pic_big,pic_square,pic,pic_large,type,website,has_added_app,founded,company_overview,mission,products,location,parking,public_transit,hours,attire,payment_options,culinary_team,general_manager,price_range,restaurant_services,restaurant_specialties,release_date,genre,starring,screenplay_by,directed_by,produced_by,studio,awards,plot_outline,network,season,schedule,written_by,band_members,hometown,current_location,record_label,booking_agent,artists_we_like,influences,band_interests,bio,affiliation,birthday,personal_info,personal_interests,members,built,features,mpg,general_info";

        private BusinessPage _businessPage;
        private CompanyPage _companyPage;
        private RestaurantPage _restaurantPage;
        private BandPage _bandPage;
        private ShowPage _showPage;
        private PersonalPage _personalPage;

        private bool _idTransformed;
        private bool _locationTransformed;

        internal PresencePage(Hashtable pageState)
            : base(pageState) {
        }

        /// <summary>
        /// Any band information associated with the page.
        /// </summary>
        public BandPage Band {
            get {
                if (_bandPage == null) {
                    _bandPage = new BandPage(EntityState);
                }
                return _bandPage;
            }
        }

        /// <summary>
        /// The URL of the big picture representing the page.
        /// </summary>
        public string BigPictureUrl {
            get {
                return GetState<string>("pic_big") ?? String.Empty;
            }
        }

        /// <summary>
        /// Biographical information associated with the page's entity.
        /// </summary>
        public string Bio {
            get {
                return GetState<string>("bio") ?? String.Empty;
            }
        }

        /// <summary>
        /// Any local business information associated with the page.
        /// </summary>
        public BusinessPage Business {
            get {
                if (_businessPage == null) {
                    _businessPage = new BusinessPage(EntityState);
                }
                return _businessPage;
            }
        }

        /// <summary>
        /// Any company information associated with the page.
        /// </summary>
        public CompanyPage Company {
            get {
                if (_companyPage == null) {
                    _companyPage = new CompanyPage(EntityState);
                }
                return _companyPage;
            }
        }

        /// <summary>
        /// Any general information specified on the page.
        /// </summary>
        public string GeneralInformation {
            get {
                return GetState<string>("general_info") ?? String.Empty;
            }
        }

        /// <summary>
        /// The unique ID of the page.
        /// </summary>
        public string ID {
            get {
                if (_idTransformed == false) {
                    return TransformID();
                }
                return GetState<string>("page_id");
            }
        }

        /// <summary>
        /// Whether the current application has been added to the page.
        /// </summary>
        public bool HasAddedApp {
            get {
                return GetState<bool>("has_added_app");
            }
        }

        /// <summary>
        /// The URL of the large picture representing the page.
        /// </summary>
        public string LargePictureUrl {
            get {
                return GetState<string>("pic_large") ?? String.Empty;
            }
        }

        /// <summary>
        /// The location of the entity associated with the page.
        /// </summary>
        public Location Location {
            get {
                if (_locationTransformed == false) {
                    return TransformLocation();
                }
                return (Location)this["location"];
            }
        }

        /// <summary>
        /// The name of the entity associated with the page.
        /// </summary>
        public string Name {
            get {
                return GetState<string>("name") ?? String.Empty;
            }
        }

        /// <summary>
        /// Any personal information associated with the page.
        /// </summary>
        public PersonalPage Personal {
            get {
                if (_personalPage == null) {
                    _personalPage = new PersonalPage(EntityState);
                }
                return _personalPage;
            }
        }

        /// <summary>
        /// The URL of the picture representing the page.
        /// </summary>
        public string PictureUrl {
            get {
                return GetState<string>("pic") ?? String.Empty;
            }
        }

        /// <summary>
        /// Any restaurant information associated with the page.
        /// </summary>
        public RestaurantPage Restaurant {
            get {
                if (_restaurantPage == null) {
                    _restaurantPage = new RestaurantPage(EntityState);
                }
                return _restaurantPage;
            }
        }

        /// <summary>
        /// Any TV show or film information associated with the page.
        /// </summary>
        public ShowPage Show {
            get {
                if (_showPage == null) {
                    _showPage = new ShowPage(EntityState);
                }
                return _showPage;
            }
        }

        /// <summary>
        /// The URL of the small-sized picture representing the page.
        /// </summary>
        public string SmallPictureUrl {
            get {
                return GetState<string>("pic_small") ?? String.Empty;
            }
        }

        /// <summary>
        /// The URL of the square picture representing the page.
        /// </summary>
        public string SquarePictureUrl {
            get {
                return GetState<string>("pic_square") ?? String.Empty;
            }
        }

        /// <summary>
        /// The type of page, based on the entity it represents.
        /// </summary>
        public string Type {
            get {
                return GetState<string>("type") ?? String.Empty;
            }
        }

        /// <summary>
        /// The URL of the web site associated with the page.
        /// </summary>
        public string WebSite {
            get {
                return GetState<string>("website") ?? String.Empty;
            }
        }

        /// <summary>
        /// Gets a property of the page by the specified name.
        /// </summary>
        /// <param name="field">The name of the property.</param>
        /// <returns>The value if the property is valid and has been requested.</returns>
        public object GetValue(string field) {
            return this[field];
        }

        private string TransformID() {
            Debug.Assert(_idTransformed == false);

            string id = FacebookResponse.CoerceString(this["page_id"]);

            this["page_id"] = id;
            _idTransformed = true;

            return id;
        }

        private Location TransformLocation() {
            Debug.Assert(_locationTransformed == false);

            Location location = null;

            Hashtable locationState = (Hashtable)this["location"];
            if (locationState != null) {
                location = new Location(locationState);
            }

            this["location"] = location;
            _locationTransformed = true;

            return location;
        }
    }
}
